<?php

define('SL_DELETE', 0);
define('SL_UPDATE', 1);
define('SL_INSERT', 2);

class stabilityLayer extends modelBase {
	protected $cols = array(
		'key' => array('type' => 'VARCHAR', 'length' => 16),
		'updates' => null,
		'time' => array('type' => 'TIMESTAMP')
	);

	protected $dbLink = true;
	protected $stable = false;

	protected $validations = array();

	protected $key;
	protected $revision;

	function __construct() {
		$this->cols['updates'] = new stabilityLayerUpdates($this->name);
		parent::__construct();
	}

	function startRevision() {
		$this->key = $this->generateKey();
		$this->revision = $this->insert(new data(array(
			'key' => $this->key,
			'time' => time()
		)));
	}
	
	function getRevision() {
		return $this->revision;
	}

	function generateKey() {
		$length = 16;
		$str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
		$key = '';
		for($i = 0; $i < 62; $i++) {
			$key .= $str[mt_rand(0, 61)];
		}
		return $key;
	}

	function getKey() {
		return $this->key;
	}

	function undoLink($messageHelperFormat = true) {
		$return =  '<a href="stability-layer/undo/'.$this->name.'/?revision='.$this->revision.'&amp;key='.$this->key.'&amp;redirect=';
		if($messageHelperFormat) {
			$return .= '[pageUrl]';
		} else {
			$return .= urlencode($this->h->core->getUrl());
		}
		$return .= '">Undo</a>';
		return $return;
	}

	function recordUpdate($type, $table, $update, $original) {
		$this->cols['updates']->insert(new data(array(
			'type' => $type,
			'table' => $table,
			'update' => $update,
			'original' => $original,
			'parentId' => $this->revision
		)));
	}

	function undo($revision, $key = null) {
		if($key!==null) {
			if($this->get($revision, array(
				'where' => new predicate('key', '=', $key),
				'results' => 'single'
			))) {
				return false;
			}
		}
		$updates = $this->getCol('updates')->get('all', array(
			'where' => new predicate('parentId', '=', $revision),
			'orderBy' => array('id', 'DESC'),
			'resultsType' => 'array'
		));
		foreach($updates as $update) {
			$tableName = $update['table'];
			$this->m->load($tableName);
			unset($table);
			$table = $this->m->$tableName;
			if($update['type']==SL_INSERT) {
				$table->delete($update['original']);
			} else if($update['type']==SL_DELETE) {
				$value = $table->SL()->get($update['update'], array(
					'results' => 'single'
				));
				$value->child('id')->setValue($update['original']);
				$table->insert($value);
			} else if($update['type']==SL_UPDATE) {
				$value = $table->SL()->get($update['update'], array(
					'results' => 'single'
				));
				$value->deleteChild('id');
				$table->update($update['original'], $value);
			}
		}
	}
}

?>
